home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / xvisrc.zip / PIPE.C < prev    next >
C/C++ Source or Header  |  1992-07-28  |  5KB  |  242 lines

  1. /* Copyright (c) 1990,1991,1992 Chris and John Downey */
  2. #ifndef lint
  3. static char *sccsid = "@(#)pipe.c    2.1 (Chris & John Downey) 7/29/92";
  4. #endif
  5.  
  6. /***
  7.  
  8. * program name:
  9.     xvi
  10. * function:
  11.     PD version of UNIX "vi" editor, with extensions.
  12. * module name:
  13.     pipe.c
  14. * module function:
  15.     Handle pipe operators.
  16. * history:
  17.     STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  18.     Originally by Tim Thompson (twitch!tjt)
  19.     Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  20.     Heavily modified by Chris & John Downey
  21.  
  22. ***/
  23.  
  24. #include "xvi.h"
  25.  
  26. static    int    p_write P((FILE *));
  27. static    long    p_read P((FILE *));
  28.  
  29. static    Xviwin    *specwin;
  30. static    Line    *line1, *line2;
  31. static    Line    *newlines;
  32.  
  33. /*
  34.  * This function is called when the ! is typed in initially,
  35.  * to specify the range; do_pipe() is then called later on
  36.  * when the line has been typed in completely.
  37.  *
  38.  * Note that we record the first and last+1th lines to make the loop easier.
  39.  */
  40. void
  41. specify_pipe_range(window, l1, l2)
  42. Xviwin    *window;
  43. Line    *l1;
  44. Line    *l2;
  45. {
  46.     /*
  47.      * Ensure that the lines specified are in the right order.
  48.      */
  49.     if (l1 != NULL && l2 != NULL && earlier(l2, l1)) {
  50.     register Line    *tmp;
  51.  
  52.     tmp = l1;
  53.     l1 = l2;
  54.     l2 = tmp;
  55.     }
  56.     line1 = (l1 != NULL) ? l1 : window->w_buffer->b_file;
  57.     line2 = (l2 != NULL) ? l2->l_next : window->w_buffer->b_lastline;
  58.     specwin = window;
  59. }
  60.  
  61. /*
  62.  * Pipe the given sequence of lines through the command,
  63.  * replacing the old set with its output.
  64.  */
  65. void
  66. do_pipe(window, command)
  67. Xviwin    *window;
  68. char    *command;
  69. {
  70.     if (line1 == NULL || line2 == NULL || specwin != window) {
  71.     show_error(window,
  72.         "Internal error: pipe through badly-specified range.");
  73.     return;
  74.     }
  75.  
  76.     newlines = NULL;
  77.     if (sys_pipe(command, p_write, p_read) && newlines != NULL) {
  78.     repllines(window, line1, cntllines(line1, line2) - 1, newlines);
  79.     update_buffer(window->w_buffer);
  80.     begin_line(window, TRUE);
  81.     } else {
  82.     show_error(window, "Failed to execute \"%s\"", command);
  83.     redraw_screen();
  84.     }
  85.     cursupdate(window);
  86. }
  87.  
  88. static int
  89. p_write(fp)
  90. FILE    *fp;
  91. {
  92.     Line    *l;
  93.     long    n;
  94.  
  95.     for (l = line1, n = 0; l != line2; l = l->l_next, n++) {
  96.     (void) fputs(l->l_text, fp);
  97.     (void) putc('\n', fp);
  98.     }
  99.     return(n);
  100. }
  101.  
  102. /*
  103.  * Returns the number of lines read, or -1 for failure.
  104.  */
  105. static long
  106. p_read(fp)
  107. FILE    *fp;
  108. {
  109.     Line    *lptr = NULL;    /* pointer to list of lines */
  110.     Line    *last = NULL;    /* last complete line read in */
  111.     Line    *lp;        /* line currently being read in */
  112.     register enum {
  113.     at_soln,
  114.     in_line,
  115.     at_eoln,
  116.     at_eof
  117.     }    state;
  118.     char    *buff;        /* text of line being read in */
  119.     int        col;        /* current column in line */
  120.     unsigned long
  121.         nlines;        /* number of lines read */
  122.  
  123.     col = 0;
  124.     nlines = 0;
  125.     state = at_soln;
  126.     while (state != at_eof) {
  127.  
  128.     register int    c;
  129.  
  130.     c = getc(fp);
  131.  
  132.     /*
  133.      * Nulls are special; they can't show up in the file.
  134.      */
  135.     if (c == '\0') {
  136.         continue;
  137.     }
  138.  
  139.     if (c == EOF) {
  140.         if (state != at_soln) {
  141.         /*
  142.          * Reached EOF in the middle of a line; what
  143.          * we do here is to pretend we got a properly
  144.          * terminated line, and assume that a
  145.          * subsequent getc will still return EOF.
  146.          */
  147.         state = at_eoln;
  148.         } else {
  149.         state = at_eof;
  150.         }
  151.     } else {
  152.         if (state == at_soln) {
  153.         /*
  154.          * We're at the start of a line, &
  155.          * we've got at least one character,
  156.          * so we have to allocate a new Line
  157.          * structure.
  158.          *
  159.          * If we can't do it, we throw away
  160.          * the lines we've read in so far, &
  161.          * return gf_NOMEM.
  162.          */
  163.         lp = newline(MAX_LINE_LENGTH);
  164.         if (lp == NULL) {
  165.             if (lptr != NULL)
  166.             throw(lptr);
  167.             return(-1);
  168.         } else {
  169.             buff = lp->l_text;
  170.         }
  171.         }
  172.  
  173.         if (c == '\n') {
  174.         state = at_eoln;
  175.         }
  176.     }
  177.  
  178.     /*
  179.      * Fake eoln for lines which are too long.
  180.      * Don't lose the input character.
  181.      */
  182.     if (col >= MAX_LINE_LENGTH - 1) {
  183.         (void) ungetc(c, fp);
  184.         state = at_eoln;
  185.     }
  186.  
  187.     switch (state) {
  188.     /*
  189.      *    case at_eof:
  190.      *        break;
  191.      */
  192.  
  193.     case at_soln:
  194.     case in_line:
  195.         state = in_line;
  196.         buff[col++] = c;
  197.         break;
  198.  
  199.     case at_eoln:
  200.         /*
  201.          * First null-terminate the old line.
  202.          */
  203.         buff[col] = '\0';
  204.  
  205.         /*
  206.          * If this fails, we squeak at the user and
  207.          * then throw away the lines read in so far.
  208.          */
  209.         buff = realloc(buff, (unsigned) col + 1);
  210.         if (buff == NULL) {
  211.         if (lptr != NULL)
  212.             throw(lptr);
  213.         return(-1);
  214.         }
  215.         lp->l_text = buff;
  216.         lp->l_size = col + 1;
  217.  
  218.         /*
  219.          * Tack the line onto the end of the list,
  220.          * and then point "last" at it.
  221.          */
  222.         if (lptr == NULL) {
  223.         lptr = lp;
  224.         last = lptr;
  225.         } else {
  226.         last->l_next = lp;
  227.         lp->l_prev = last;
  228.         last = lp;
  229.         }
  230.  
  231.         nlines++;
  232.         col = 0;
  233.         state = at_soln;
  234.         break;
  235.     }
  236.     }
  237.  
  238.     newlines = lptr;
  239.  
  240.     return(nlines);
  241. }
  242.